package com.pf.common.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.ThreadPoolExecutor;

/**
 * @author PanFei
 * @version 1.0.0
 * @createTime 2023/7/16 20:07
 */
@Slf4j
@Configuration
@EnableAsync
public class ExecutorConfig {

    /**
     * 核心线程数
     */
    @Value("${spring.task.execution.pool.core-size:2}")
    private int corePoolSize;

    /**
     * 最大线程数
     */
    @Value("${spring.task.execution.pool.max-size:2}")
    private int maxPoolSize;

    /**
     * 阻塞队列大小
     */
    @Value("${spring.task.execution.pool.queue-capacity:2}")
    private int queueCapacity;

    /**
     * 线程空闲后最大存活时间
     */
    @Value("${spring.task.execution.pool.keep-alive:60}")
    private int keepAliveSeconds;


    /**
     * 定义的第一个线程池：推荐使用
     *
     * @return
     */
    @Bean
    public ThreadPoolTaskExecutor asyncLogExecutor() {
        ThreadPoolTaskExecutor threadPoolTaskExecutor = new CustomThreadPoolTaskExecutor();
        // 核心线程数
        threadPoolTaskExecutor.setCorePoolSize(corePoolSize);
        // 是否允许核心线程数超时
        threadPoolTaskExecutor.setAllowCoreThreadTimeOut(true);
        // 最大线程数
        threadPoolTaskExecutor.setMaxPoolSize(maxPoolSize);
        // 配置队列大小
        threadPoolTaskExecutor.setQueueCapacity(queueCapacity);
        // 空闲线程保留时间
        threadPoolTaskExecutor.setKeepAliveSeconds(keepAliveSeconds);
        // 配置线程池前缀
        threadPoolTaskExecutor.setThreadNamePrefix("async-service-");
        // 拒绝策略
        threadPoolTaskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());
        // 线程池关闭的时候等待所有任务都完成后，再继续销毁其他的bean，这样这些异步任务的销毁就会先于数据库连接池对象的销毁
        threadPoolTaskExecutor.setWaitForTasksToCompleteOnShutdown(true);
        // 设置线程池中任务的等待时间，如果超过这个时间还没有销毁就强制销毁，以确保应用最后能够关闭，而不是阻塞住
        threadPoolTaskExecutor.setAwaitTerminationSeconds(60);
        threadPoolTaskExecutor.initialize();
        return threadPoolTaskExecutor;
    }
}
